#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
int client_fd;
#define SERVERPORT 8888

void handle_sigio(int signum) {
    char    buffer[1024];
    ssize_t num_bytes;

    printf("signum:%d\n", signum);

    // 异步读取
    num_bytes = read(client_fd, buffer, sizeof(buffer));
    if (num_bytes > 0) {
        // 处理读取到的数据
        printf("Received: %.*s\n", (int)num_bytes, buffer);
    }
    else if (num_bytes == 0) {
        // 客户端关闭连接
        printf("Client closed the connection.\n");
        exit(0);
    }
    else {
        // 读取错误
        perror("read");
        exit(1);
    }
}

int create_socket(const char* ip, int port) {
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("socket");
        return -1;
    }

    // 绑定和监听...
    struct sockaddr_in laddr;
    laddr.sin_family = AF_INET;
    laddr.sin_port   = htons(port);
    inet_pton(AF_INET, ip, &laddr.sin_addr);

    // 设置地址重用
    int optval = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) {
        perror("setsockopt");
        return -1;
    }

    if (bind(server_fd, (struct sockaddr*)&laddr, sizeof(laddr)) < 0) {
        perror("bind");
        return -1;
    }

    if (listen(server_fd, 200) < 0) {
        perror("listen");
        return -1;
    }
    return server_fd;
}

void config_signal() {
    // 设置信号处理函数
    struct sigaction sa;
    sa.sa_handler = handle_sigio;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGIO, &sa, NULL) == -1) {
        perror("sigaction");
        exit(1);
    }
}

int main() {
    config_signal();
    
    // 创建套接字
    int server_fd = create_socket("0.0.0.0", SERVERPORT);
    if (server_fd == -1)
        exit(-1);

    while (1) {
        // 接受连接请求
        client_fd = accept(server_fd, NULL, NULL);
        printf("accept:%d\n", client_fd);

        // 设置客户端套接字为非阻塞模式
        int flags = fcntl(client_fd, F_GETFL, 0);
        fcntl(client_fd, F_SETFL, flags | O_NONBLOCK);

        // 将文件描述符与进程关联，以接收 SIGIO 信号
        if (fcntl(client_fd, F_SETOWN, getpid()) == -1) {
            perror("fcntl(F_SETOWN)");
            exit(1);
        }

        // 设置套接字为异步通知模式
        if (fcntl(client_fd, F_SETFL, O_ASYNC) == -1) {
            perror("fcntl(O_ASYNC)");
            exit(1);
        }
    }

    // 关闭套接字
    close(client_fd);
    close(server_fd);

    return 0;
}
